Day 11: Inheritance
Inheritance is when a new class (child) inherits attributes and behaviors from an existing class (parent). It increases code reusability and expresses “is-a” relationships. For example, “a Dog is an Animal” can be modeled through inheritance.
Basic Inheritance Structure
Use the extends keyword to inherit from a parent class.
// Parent class
class Animal {
String name;
int age;
Animal(String name, int age) {
this.name = name;
this.age = age;
}
void eat() {
System.out.println(name + " is eating.");
}
void sleep() {
System.out.println(name + " is sleeping.");
}
void showInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
// Child class
class Dog extends Animal {
String breed;
Dog(String name, int age, String breed) {
super(name, age); // Call parent constructor
this.breed = breed;
}
// Child-specific method
void bark() {
System.out.println(name + " barks! Woof woof!");
}
void fetch(String item) {
System.out.println(name + " fetches the " + item + ".");
}
}
class Cat extends Animal {
boolean isIndoor;
Cat(String name, int age, boolean isIndoor) {
super(name, age);
this.isIndoor = isIndoor;
}
void purr() {
System.out.println(name + " purrs softly.");
}
}
public class InheritanceBasic {
public static void main(String[] args) {
Dog dog = new Dog("Buddy", 3, "Jindo");
dog.showInfo(); // Can use parent method
dog.eat(); // Can use parent method
dog.bark(); // Child-specific method
dog.fetch("ball");
Cat cat = new Cat("Whiskers", 2, true);
cat.showInfo();
cat.sleep();
cat.purr();
}
}
Method Overriding
Redefine a parent class method in the child class. Use the @Override annotation to indicate intent.
class Shape {
String color;
Shape(String color) {
this.color = color;
}
double area() {
return 0;
}
void describe() {
System.out.println(color + " shape, area: " + area());
}
}
class Circle extends Shape {
double radius;
Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
@Override
void describe() {
System.out.printf("%s circle (radius: %.1f), area: %.2f%n",
color, radius, area());
}
}
class Rectangle extends Shape {
double width;
double height;
Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
@Override
void describe() {
System.out.printf("%s rectangle (%.1f x %.1f), area: %.2f%n",
color, width, height, area());
}
}
public class OverrideExample {
public static void main(String[] args) {
Circle circle = new Circle("Red", 5.0);
Rectangle rect = new Rectangle("Blue", 4.0, 6.0);
circle.describe(); // Red circle (radius: 5.0), area: 78.54
rect.describe(); // Blue rectangle (4.0 x 6.0), area: 24.00
}
}
The super Keyword and Constructor Chaining
Use super to call a parent’s constructor or methods.
class Vehicle {
String brand;
int year;
int speed;
Vehicle(String brand, int year) {
this.brand = brand;
this.year = year;
this.speed = 0;
System.out.println("Vehicle constructor called");
}
void accelerate(int amount) {
speed += amount;
System.out.println(brand + " accelerating: current speed " + speed + "km/h");
}
void brake(int amount) {
speed = Math.max(0, speed - amount);
System.out.println(brand + " braking: current speed " + speed + "km/h");
}
@Override
public String toString() {
return brand + " (" + year + ") - " + speed + "km/h";
}
}
class ElectricCar extends Vehicle {
int batteryLevel;
ElectricCar(String brand, int year, int batteryLevel) {
super(brand, year); // Must call parent constructor on the first line
this.batteryLevel = batteryLevel;
System.out.println("ElectricCar constructor called");
}
@Override
void accelerate(int amount) {
if (batteryLevel <= 0) {
System.out.println("Battery is low!");
return;
}
super.accelerate(amount); // Call parent method
batteryLevel -= amount / 10;
System.out.println("Battery remaining: " + batteryLevel + "%");
}
void charge() {
batteryLevel = 100;
System.out.println(brand + " fully charged!");
}
@Override
public String toString() {
return super.toString() + ", Battery: " + batteryLevel + "%";
}
}
public class SuperExample {
public static void main(String[] args) {
ElectricCar tesla = new ElectricCar("Tesla Model 3", 2024, 80);
System.out.println(tesla);
tesla.accelerate(100);
tesla.accelerate(50);
System.out.println(tesla);
}
}
final and the Object Class
Use the final keyword to restrict inheritance or overriding, and understand Object — the ultimate parent of all classes.
// final class: cannot be inherited
// final class Immutable { }
// final method: cannot be overridden
class Parent {
final void cannotOverride() {
System.out.println("This method cannot be overridden.");
}
}
// Overriding Object class methods
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person other = (Person) obj;
return age == other.age && name.equals(other.name);
}
@Override
public int hashCode() {
return java.util.Objects.hash(name, age);
}
}
public class ObjectExample {
public static void main(String[] args) {
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
Person p3 = new Person("Bob", 30);
// Effect of toString override
System.out.println(p1); // Person{name='Alice', age=25}
// Effect of equals override
System.out.println(p1.equals(p2)); // true (same content)
System.out.println(p1.equals(p3)); // false
// instanceof: type checking
System.out.println(p1 instanceof Person); // true
System.out.println(p1 instanceof Object); // true (all objects)
}
}
Today’s Exercises
-
Employee Hierarchy: Create an
Employeeparent class (name, salary) and child classesManager(department name, bonus rate) andDeveloper(programming language, level). OverridecalculatePay()in each. -
Implementing toString and equals: Properly override
toString(),equals(), andhashCode()in aBookclass. Books with the same ISBN should be considered equal. -
Shape Hierarchy: Define
area()andperimeter()methods in aShapeparent class, and implementTriangle(base, height, three side lengths) andTrapezoid(top side, bottom side, height) using inheritance.